package com.pansoft.openplanet.util;

import android.content.Context;

import com.efounder.constant.EnvironmentVariable;
import com.efounder.utils.ResStringUtil;
import com.pansoft.openplanet.R;
import com.pansoft.openplanet.bean.Account;
import com.pansoft.openplanet.constant.IPAssetsConstant;
import com.pansoft.openplanet.db.AccountDao;
import com.utilcode.util.LogUtils;
import com.utilcode.util.ToastUtils;

import net.sf.json.JSONObject;

import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Bool;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.crypto.Credentials;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.TransactionEncoder;
import org.web3j.tx.Contract;
import org.web3j.utils.Convert;
import org.web3j.utils.Numeric;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @author : zzj
 * @e-mail : zhangzhijun@pansoft.com
 * @date : 2018/11/214:32
 * @desc : 商城夺宝交易工具类
 * @version: 1.0
 */
public class TreasureTransferUtils {
    private static final String TAG = "TreasureTransferUtils";
    /**
     * 夺宝 BaseUrl   （张明成)
     */
    public static final String BASE_TREASURE_URL = EnvironmentVariable.getProperty("mallTreasureUrl") + "/osp-treasure";

    private static TreasureTransferUtils instance = new TreasureTransferUtils();

    public static TreasureTransferUtils getInstance() {
        return instance;
    }

    private EthTokenTransactionManager transactionManager;
    private Account account;

    /**
     * 夺宝币交易
     *
     * @param nonce            请求下来的转账次数
     * @param amount           购买的数量（转账的金额）
     * @param credentials      类似签名密钥
     * @param gasPrice         旷工费（手续费）
     * @param constractAddress 给我的合约地址 测试 0x1fe7014f1aed0df06cd994388d64d276bcd37604
     * @param callBack
     */
    public void startTreasureTransaction(BigInteger nonce, String goodsId, BigInteger amount, Credentials credentials,
                                         BigInteger gasPrice, String constractAddress, String orderNumber,
                                         String quantity1, String quantity2, final EthTokenTransactionManager.TransactionCallBack callBack) {
        String hexValue = getTreasureDataSignHex(nonce, goodsId, quantity1, quantity2, credentials, gasPrice, constractAddress);
        //接口调用参数
        HashMap<String, String> map = new HashMap<>();
        map.put("signedTransactionData", hexValue);
        map.put("goodsId", goodsId);
        map.put("quantity1", quantity1);
        map.put("quantity2", quantity2);
        map.put("orderNumber", orderNumber);
        //调用接口进行交易
        StarAssetRequestUtil.getRequest(TAG, BASE_TREASURE_URL + "/winTreasure/buyChance",
                map, new StarAssetRequestUtil.SARequestCallback() {
                    @Override
                    public void onSuccess(String response) {
                        try {
                            JSONObject jsonObject = JSONObject.fromObject(response);
                            LogUtils.i(jsonObject.toString());
                            if (jsonObject.containsKey("code") && jsonObject.getInt("code") == 0) {
                                //交易成功，返回交易编号
                                callBack.transactionResult(true, response);

                            } else {
                                callBack.transactionResult(false, ResStringUtil.getString(R.string.open_planet_transaction_fail));
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            callBack.transactionResult(false, ResStringUtil.getString(R.string.open_planet_transaction_fail));
                        }
                    }

                    @Override
                    public void onFail(String error) {
                        callBack.transactionResult(false, ResStringUtil.getString(R.string.open_planet_transaction_fail));
                    }
                });
    }

    /**
     * 夺宝币交易生成签名
     *
     * @param nonce            请求下来的转账次数
     * @param goodId           商品id
     * @param credentials
     * @param gasPrice
     * @param constractAddress
     * @return
     */
    public String getTreasureDataSignHex(BigInteger nonce, String goodId, String quantity1, String quantity2,
                                         Credentials credentials, BigInteger gasPrice, String constractAddress) {
        //交易签名
        String hexValue = null;
        //方法名 交易
        String methodName = "buyChance";
        //输入参数
        List<Type> inputParameters = new ArrayList<>();
        //转账代币 金额
//        Uint256 value = new Uint256(amount);
        //商品编号
        Uint256 goodIdValue = new Uint256(Long.valueOf(goodId));
        //夺宝参数
        Uint256 quantity1Value = new Uint256(Long.valueOf(quantity1));
        Uint256 quantity2Value = new Uint256(Long.valueOf(quantity2));
        //商品编号
        inputParameters.add(goodIdValue);
        inputParameters.add(quantity1Value);
        inputParameters.add(quantity2Value);
        //购买编号1
//        inputParameters.add(value);
        //购买编号2，现在默认为0
//        inputParameters.add(new Uint256(0L));
        //一个空集合
        List<TypeReference<?>> outputParameters = new ArrayList<>();
        TypeReference<Bool> typeReference = new TypeReference<Bool>() {
        };
        outputParameters.add(typeReference);

        //创建function
        Function function = new Function(methodName, inputParameters, outputParameters);
        //获取data
        String data = FunctionEncoder.encode(function);
        LogUtils.i("data:" + data);
        //创建原始交易
        RawTransaction transaction = RawTransaction.createTransaction(nonce, gasPrice, Contract.GAS_LIMIT, constractAddress, data);
        //签名Transaction，这里要对交易做签名
        byte[] signedMessage = null;
        signedMessage = TransactionEncoder.signMessage(transaction, credentials);
//        //这里我们拿到了交易的签名
        hexValue = Numeric.toHexString(signedMessage);
        return hexValue;
    }

    /**
     * @param mContext        上下文
     * @param payAddress      支付地址
     * @param orderNumber     订单号
     * @param goodsId         商品id  （区块链接口生成的  不是商品的id）
     * @param contractAddress 合约地址
     * @param gasPrice1       矿工费
     * @param amount          支付金额
     * @param quantity1       购买数量
     */
    public void startTreasureTransfer(Context mContext, final String payAddress, final String orderNumber
            , final String goodsId, final String contractAddress, final String gasPrice1, final String quantity1
            , final String amount
            , final EthTokenTransactionManager.TransactionCallBack callBack) {

        transactionManager = new EthTokenTransactionManager(mContext);
        account = new AccountDao(mContext).getAccount(payAddress);
        transactionManager.loadCredentialsASync(account,
                new EthTokenTransactionManager.LoadCredentialsCallBack() {
                    @Override
                    public void loadResult(boolean isSuccess, final Credentials credentials) {
                        if (!isSuccess) {
                            callBack.transactionResult(false, ResStringUtil.getString(R.string.open_planet_transaction_fail));
                            ToastUtils.showShort(ResStringUtil.getString(R.string.open_planet_transfer_fail));
                            return;
                        }
                        //2.获取nonce
//                        LogUtils.i("获取nonce", credentials.getAddress());
                        transactionManager.getTransactionNonce(payAddress, IPAssetsConstant.CHAIN_ID_TURBOCHAIN, new EthTokenTransactionManager.NonceCallBack() {
                            @Override
                            public void nonceResult(boolean isSuccess, BigInteger nonce) {
                                if (!isSuccess) {
                                    callBack.transactionResult(false, ResStringUtil.getString(R.string.open_planet_transaction_fail));
//                                    ToastUtils.showShort(ResStringUtil.getString(R.string.open_planet_transfer_fail));
                                    return;
                                }
                                //3.开始转账
//                                LogUtils.i("开始转账", nonce);
                                //智能合约转账
                                //矿工费
                                BigInteger gasPrice = Convert.toWei(gasPrice1, Convert.Unit.ETHER).toBigInteger().divide(Contract.GAS_LIMIT);
//                                LogUtils.d("GAS:" + gasPrice.toString());
                                startTreasureTransaction(nonce, goodsId,
                                        Convert.toWei(amount, Convert.Unit.ETHER).toBigInteger(),
                                        credentials, gasPrice, contractAddress, orderNumber,
                                        quantity1, "0", new EthTokenTransactionManager.TransactionCallBack<String>() {
                                            @Override
                                            public void transactionResult(boolean isSuccess, String result) {
                                                if (!isSuccess) {
                                                    // showTransactionResult(false,ResStringUtil.getString(R.string.open_planet_transaction_fail));
                                                    callBack.transactionResult(false, ResStringUtil.getString(R.string.open_planet_transaction_fail));
                                                    // showTransactionResult(true, result);
                                                    return;
                                                }
                                                //转账成功
                                                callBack.transactionResult(true, result);
                                            }
                                        });
                            }
                        });
                    }
                });
    }

    /**
     * 关闭Observable，防止内存泄漏
     */
    public void closeTransaction() {
        if (transactionManager != null) {
            transactionManager.dispose();
            transactionManager = null;
        }
    }
}
